package recharge

import (
	"context"
	"errors"
	"fmt"
	"net/http"

	userrpc2 "gitee.com/liuxuezhan/ar-platform/rpc-client/userServiceClient/userrpc"
	"github.com/jinzhu/copier"

	errcode "gitee.com/liuxuezhan/ar-platform/assets-api/internal/logic"
	"gitee.com/liuxuezhan/ar-platform/assets-api/internal/pay"
	"gitee.com/liuxuezhan/ar-platform/assets-api/internal/pay/base"
	"gitee.com/liuxuezhan/ar-platform/assets-api/internal/service/setting_config"
	"gitee.com/liuxuezhan/ar-platform/assets-api/internal/svc"
	"gitee.com/liuxuezhan/ar-platform/assets-api/internal/types"
	"gitee.com/liuxuezhan/ar-platform/assets-api/pkg/xerrors"
	"gitee.com/liuxuezhan/ar-platform/base-common/headInfo"
	"gitee.com/liuxuezhan/ar-platform/base-common/pkg/xcode"
	"gitee.com/liuxuezhan/ar-platform/rpc-client/assetsClient/rpc"
	"gitee.com/liuxuezhan/ar-platform/rpc-client/userServiceClient/userrpc"

	"github.com/zeromicro/go-zero/core/logx"
)

type RechargeLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewRechargeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RechargeLogic {
	return &RechargeLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *RechargeLogic) Recharge(req *types.RechargeRequest) (*types.RechargeResponse, error) {

	userId := headInfo.GetTokenUid(l.ctx)
	if userId == 0 {
		return nil, xerrors.ErrInvalidToken
	}

	userGroupInfoRe := &userrpc2.UserGroupInfoRequest{UserId: userId}
	userResult, err := l.svcCtx.UserRpc.UserGetGroupInfo(l.ctx, userGroupInfoRe)
	if err != nil {
		logx.Error(fmt.Sprintf("WithdrawLogic:Recharge:UserGetGroupInfo, %v", err))
		return nil, xcode.New(500, "system getGroupInfo error")
	} else if perm := userResult.Data.Perms; perm != nil && !perm.Charge {
		return nil, xcode.New(500, "no recharge permission")
	}

	// TODO wait for comfier business
	// if withdraw.IsOpen(l.svcCtx, l.ctx, common.RechargeVipConfig, "status") == 1 {
	//	response, err2 := validVipConfig(l, userId)
	//	if err2 != nil {
	//		return response, err2
	//	}
	// }
	amount := req.Amount
	// 1. verify data
	in := rpc.RechargeChannelInfoRequest{Id: int64(req.RechargeChannelId)}
	channel, err := l.svcCtx.AssetsRpc.PayRecharge.RechargeChannelInfo(l.ctx, &in)
	if err != nil {
		return nil, err
	}
	// check whether the amount falls into the range
	if amount < channel.MinAmount || amount > channel.MaxAmount {
		return nil, errcode.NewAssetsRPCError(errcode.ErrInvalidAmount)
	}

	if setting_config.OpenRechargeLocalWallet(l.ctx, l.svcCtx.CommonSettingRpc) {
		// Fixme
		if req.RechargeTypeId == 2 {
			if req.Name == "" || req.Telephone == "" {
				return nil, xcode.New(http.StatusBadRequest, "name, phone must.")
			}
		}
	}

	in2 := rpc.RechargeCreateRequest{
		UserId:    userId,
		ChannelId: int64(req.RechargeChannelId),
		Type:      req.RechargeTypeId,
		Amount:    amount,
		UserInfo: &rpc.RechargeUserInfo{
			Phone:       req.Telephone,
			Name:        req.Name,
			UsdtAddress: req.LocalUsdt.UserAddress,
			UsdtAmount:  req.LocalUsdt.UsdtAmount,
		},
		TenantId: req.LocalUsdt.TenantId,
		Fackbook: &rpc.Facebook{},
		Coin:     req.CoinType,
	}
	copier.Copy(in2.Fackbook, &req.Facebook)
	// 2. generator orderNo and	create recharge order & set status to pending
	out2, err := l.svcCtx.AssetsRpc.PayRecharge.RechargeCreate(l.ctx, &in2)
	if err != nil {
		return nil, err
	}

	in2.Fackbook.UserAgent = headInfo.GetUserAgent(l.ctx)
	// build config for third pay
	config := base.Config{
		Url:        channel.Url,
		SecretKey:  channel.SecretKey,
		MerchantId: channel.MerchantId,
		PrivateKey: channel.PrivateKey,
		AppId:      channel.AppId,
		AppCode:    channel.AppCode,
		ReturnUrl:  channel.ReturnUrl,
		NotifyUrl:  channel.NotifyUrl,
		PublicKey:  channel.PubKey,
	}
	thirdPay := pay.NewFactory(channel.MappingCode, config)
	if thirdPay == nil {
		return nil, xcode.New(http.StatusBadRequest, "Unknown pay type.")
	}
	params := map[string]interface{}{
		"amount": amount,
		// "payType": req.Type,
		"orderNo": out2.OrderNo,
		"user_id": userId,
		//
		"name":           channel.Name,
		"ip":             "127.0.0.1",
		"nonceStr":       "123456",
		"notifyUrl":      "https://localhost/recharge/notify",
		"returnUrl":      "https://localhost/recharge/notify",
		"rechargeTypeId": req.RechargeTypeId,
	}
	payRet, err := thirdPay.Pay(l.ctx, params)
	if err != nil {
		return nil, err
	}

	// 记录第三方支付订单号
	if payRet.OrderNo != "" {
		_, err = l.svcCtx.AssetsRpc.PayRecharge.RechargeUpdateOrderId(l.ctx, &rpc.RechargeUpdateOrderIdRequest{OrderNo: out2.OrderNo, OrderId: payRet.OrderNo})
		if err != nil {
			return nil, err
		}
	}

	return &types.RechargeResponse{
		Url: payRet.Url,
		// Address: payRet.Address,
		// QrCode:  payRet.QrCode,
		OrderNo: payRet.OrderNo,
	}, nil
}

func validVipConfig(l *RechargeLogic, userId int64) (*types.RechargeResponse, error) {
	client, _ := l.svcCtx.UserServiceRPC.UserGetByClient(l.ctx, &userrpc.UserGetByClientRequest{Id: userId})
	if client == nil {
		return nil, errors.New("User ID not exists. ")
	}
	list, err := l.svcCtx.AssetsRpc.PayRecharge.RechargeVipLevelList(l.ctx, &rpc.RechargeVipLevelListRequest{Viplevel: &client.User.VipLevel})
	if err != nil {
		return nil, errors.New(fmt.Sprintf("chekc vip config error : %v\n", err))
	}

	if list.Records[0].Amount < 1000 || list.Records[0].Times < 20 {
		return nil, errors.New(fmt.Sprintf("over the limit"))
	}
	return nil, nil
}
